from flask import Blueprint, request, current_app
from werkzeug.security import check_password_hash, generate_password_hash
from flask_jwt_extended import create_access_token, get_jwt_identity, jwt_required, verify_jwt_in_request
from user_agents import parse
from flask_json import as_json
from app import db, ip2region_cb
from app.models import BlogUser, CommonResult, LoginLog
from app.common.utils import get_remote_address
from app.common.ip_xdb_searcher import XdbSearcher
from app.form.login_form import LoginForm
from app.form.register_form import RegisterForm
from app.form.change_password_form import ChangePasswordForm

log = current_app.logger
user = Blueprint('user', __name__, url_prefix='/user')


# 注册蓝图
def register_controller(app):
    app.register_blueprint(user)


# 获取生成的密码hash
@user.post('/generate_password')
@as_json
def generate_password():
    password = request.get_json().get('password')
    if password:
        hash = generate_password_hash(password)
        return CommonResult(data=hash)
    else:
        return CommonResult(code=500, msg='明文密码不能为空')


# 用户注册
@user.post('/register')
@as_json
def user_register():
    # 表单验证
    RegisterForm().api_validate()
    data = request.get_json()
    username = data.get('username')
    # 密码校验
    password = data.get('password')
    avatar = data.get('avatar')
    super_user = data.get('super_user')
    active_user = data.get('active_user')
    staff_user = data.get('staff_user')
    # 填充数据到对象
    user = BlogUser(
        username=username,
        password=generate_password_hash(password),
        avatar=avatar,
        super_user=super_user,
        active_user=active_user,
        staff_user=staff_user
    )
    # 保存到数据库
    db.session.add(user)
    db.session.commit()
    return CommonResult(msg='添加成功')


# 用户登录
@user.post('/login')
@as_json
def login():
    form = LoginForm().api_validate()
    username = form.username.data
    # 查询用户
    login_user = BlogUser.query.filter_by(username=username, active_user=True).first()
    if login_user is None:
        return CommonResult(code=500, msg='用户名或密码有误')
    # 判断密码是否正确
    password = form.password.data
    if check_password_hash(login_user.password, password):
        access_token = create_access_token(identity=login_user.id)
        # 添加登录日志
        ua_string = request.headers.get("User-Agent")
        user_agent = parse(ua_string)
        # 获取客服端的ip
        ip = get_remote_address(request)
        # 解析ip归属地
        searcher = XdbSearcher(contentBuff=ip2region_cb)
        region_str = searcher.search(ip)
        searcher.close()
        # 插入数据库
        login_log = LoginLog(
            user_id=login_user.id,
            ip=ip,
            ip_address=region_str,
            source=user_agent.browser.family,
            user_agent=ua_string
        )
        db.session.add(login_log)
        db.session.commit()
        return CommonResult(data=access_token, msg='登录成功')
    else:
        return CommonResult(code=500, msg='用户名或密码有误')


# 获取登录用户信息
@user.get('/current_user')
@jwt_required()
@as_json
def current_user():
    user_id = get_jwt_identity()
    user = BlogUser.query.get(user_id)
    if user is None:
        # 验证一下有效性
        verify_jwt_in_request()
        return CommonResult(code=500, msg='登录用户不存在')
    user.password = None
    return CommonResult(data=user)


# 退出登录
@user.get('/logout')
@jwt_required()
def logout():
    pass


# 修改密码
@user.post('/change_password')
@jwt_required()
@as_json
def change_password():
    # 参数校验
    ChangePasswordForm().api_validate()
    data = request.get_json()
    # 确认新密码
    password_confirm = data.get('password_confirm')
    # 获取登录用户
    user_id = get_jwt_identity()
    login_user = BlogUser.query.get(user_id)
    # 修改密码
    login_user.password = generate_password_hash(password_confirm)
    db.session.commit()
    return CommonResult(msg='密码修改成功，请重新登录')
